home *** CD-ROM | disk | FTP | other *** search
/ Emulator Universe CD / emulatoruniversecd1998.iso / CPC / Utils / CpcFile System / TOOLS.C < prev    next >
Encoding:
C/C++ Source or Header  |  1996-02-08  |  16.2 KB  |  752 lines

  1.  
  2. /*                <<<<Last Modified: Thu Feb 08 15:08:32 1996>>>>
  3. ------------------------------------------------------------------------------
  4.  
  5.     =====
  6.     CPCfs  --  t o o l s . c  --  Auxiliary functions
  7.     =====
  8.  
  9.     Version 0.85                    (c) February '96 by Derik van Zuetphen
  10. ------------------------------------------------------------------------------
  11. */
  12.  
  13.  
  14. #include "cpcfs.h"
  15.  
  16.  
  17. /*************
  18.   Auxiliaries
  19.  *************/
  20.  
  21. void printm(int verb, char *fmt, ...)  {
  22. /*   ^^^^^^ */
  23. va_list    args;
  24. const char    highlight[] = "\x1B[0;31;1m";    /* light red */
  25. const char    unhighlight[] = "\x1B[0m";
  26.  
  27.     va_start (args, fmt);
  28.     if (Verb >= verb) {
  29.         if (verb>9) printf("%s",highlight);
  30.         vprintf(fmt,args);
  31.         if (verb>9) {
  32.             printf("%s",unhighlight);
  33.             fflush(stdout);
  34.         }
  35.     }
  36.     va_end(args);
  37. }
  38.  
  39. void putcharm(int verb, char ch)  {
  40. /*   ^^^^^^^^ */
  41.     if (Verb >= verb) putchar(ch);
  42. }
  43.  
  44.  
  45.  
  46.  
  47. char *lower(char *s)  {
  48. /*    ^^^^^ */
  49. char    *p=s;
  50.     while (*s) {
  51.         *s=tolower(*s);
  52.         s++;
  53.     }
  54.     return p;
  55. }
  56.  
  57. char *upper(char *s)  {
  58. /*    ^^^^^ */
  59. char    *p=s;
  60.     while (*s) {
  61.         *s=toupper(*s);
  62.         s++;
  63.     }
  64.     return p;
  65. }
  66.  
  67.  
  68. char *append_suffix (char *name, char *suffix) {
  69. /*    ^^^^^^^^^^^^^
  70. Appends <suffix> to <name>, but not if the name already ends with <suffix>.
  71. <name> must point to sufficient space. Returns <name> */
  72. char    *p, *ds, *dot;
  73.  
  74.     p=name;
  75.     ds=dot=NULL;
  76.     while (*p) {
  77.         if (*p==DIRSEPARATOR)    ds=p;
  78.         if (*p=='.')        dot=p;            
  79.         p++;
  80.     }
  81.     if ((dot==NULL)||(dot<ds)) {
  82.         strcat(name,".");
  83.         strcat(name,suffix);
  84.     }
  85.     return name;
  86. }
  87.  
  88.  
  89. int errorf (bool perr,const char *fmt, ...) {
  90. /*  ^^^^^^
  91. Writes a formatted errormessage to stderr and appends a system errormessage
  92. if <perr> set. The message in <fmt> should not end with \n.
  93. Always returns -1. */
  94.  
  95. va_list    args;
  96.     if (Verb<1) return -1;
  97.  
  98.     va_start(args,fmt);
  99.     vfprintf(stderr,fmt,args);
  100.     va_end(args);
  101.     if (perr) {
  102. #if UNIX    
  103.         fprintf(stderr,": ");
  104. #endif
  105. /* DOS put always a colon before the error message, UNIX only if the argument
  106. to perror is not empty */
  107.         perror("");
  108.     } else
  109.         fputc(10,stderr);
  110.     return -1;
  111. }
  112.  
  113. /* attribute names for parsing and writing attributes */
  114.  
  115. const char    *attr_name[3][11] = {
  116.     {"A=ON", "SYS", "R/O", "F8=ON", "F7=ON", "F6=ON", "F5=ON",   /* set */
  117.                    "F4=ON", "F3=ON", "F2=ON", "F1=ON" },
  118.     {"A=OFF","DIR", "R/W", "F8=OFF","F7=OFF","F6=OFF","F5=OFF",  /* reset */
  119.                    "F4=OFF","F3=OFF","F2=OFF","F1=OFF" },
  120.     {"A", "SYS", "R/O", "8", "7", "6", "5", "4", "3", "2", "1" } /* short */
  121. };
  122.  
  123. const char    *attr_empty[] = {"-", "   ", " "};
  124.  
  125.  
  126. const char *show_attr(int mask, int attr, bool always) {
  127. /*          ^^^^^^^^^
  128. Answer a representation for attribute <attr>, if it appears in <mask>,
  129. If <always> is set, answer also a string for zero-attributes */
  130.  
  131.     if (mask & attr) {    /* attribute set */
  132.         switch (attr) {
  133.         case ATTR_A: return attr_name[2][0];
  134.         case ATTR_S: return attr_name[2][1];
  135.         case ATTR_R: return attr_name[2][2];
  136.         case ATTR_8: return attr_name[2][3];
  137.         case ATTR_7: return attr_name[2][4];
  138.         case ATTR_6: return attr_name[2][5];
  139.         case ATTR_5: return attr_name[2][6];
  140.         case ATTR_4: return attr_name[2][7];
  141.         case ATTR_3: return attr_name[2][8];
  142.         case ATTR_2: return attr_name[2][9];
  143.         case ATTR_1: return attr_name[2][10];
  144.         }
  145.     } else if (always) /* attribute not set and output required */
  146.         switch (attr) {
  147.         case ATTR_S: return attr_name[1][1];
  148.         case ATTR_R: return attr_name[1][2];
  149.         default:     return attr_empty[0];
  150.         }
  151.     else {    /* only spaces, attribute not set and no output */
  152.         switch (attr) {
  153.         case ATTR_R: return attr_empty[1];
  154.         case ATTR_S: return attr_empty[1];
  155.         default:     return attr_empty[2];
  156.         }
  157.     }
  158.     errorf(FALSE,"--==>>> show_attr");
  159.     return NULL;
  160. }
  161.  
  162.  
  163. const char* show_all_attr(int att, bool always) {
  164. /*          ^^^^^^^^^^^^^
  165. Show all attribues like "R/O SYS A 1234 5678" or "R/W DIR - ---- ----"
  166. */
  167.  
  168. static char buf[25];
  169.     sprintf(buf,"%s %s %s %s%s%s%s %s%s%s%s",
  170.         show_attr(att,ATTR_R,always),
  171.         show_attr(att,ATTR_S,always),
  172.         show_attr(att,ATTR_A,always),
  173.         show_attr(att,ATTR_1,always),
  174.         show_attr(att,ATTR_2,always),
  175.         show_attr(att,ATTR_3,always),
  176.         show_attr(att,ATTR_4,always),
  177.         show_attr(att,ATTR_5,always),
  178.         show_attr(att,ATTR_6,always),
  179.         show_attr(att,ATTR_7,always),
  180.         show_attr(att,ATTR_8,always));
  181.     return buf;
  182. }
  183.  
  184.  
  185. int parse_attr(char *str, int *mask, bool *set) {
  186. /*  ^^^^^^^^^^
  187. Parse the given string <str> as a attribute name. Set the <*mask> to the
  188. recognized attribut, and <set> whether the attribut is requested to set.
  189. Answer -1, if <str> is not a valid attribute name.
  190. */
  191. int    i, j;
  192. char    s[INPUTLEN];
  193.  
  194.     strcpy(s,str);
  195.     upper(s);
  196.     for (i=0;i<2;i++) {    /* set, reset */
  197.         for (j=0;j<11;j++) {    /* all attributs */
  198.             if (strcmp(s,attr_name[i][j])==0) {
  199.                 *set = (i==0);
  200.                 *mask = 0x1 << j;
  201.                 return 0;
  202.             }
  203.         }
  204.     }
  205.  
  206.     return -1;
  207. }
  208.  
  209.  
  210.  
  211.  
  212. void do_break() {
  213. /*   ^^^^^^^^
  214. Jump to interactive mode or exit */
  215.     printm(3," [Aborted]\n");
  216.     if (Interactive)
  217.         longjmp(break_entry,1);
  218.     else
  219.         exit(2);
  220. }
  221.  
  222.  
  223. void *Malloc(int bytes) {
  224. /*    ^^^^^^
  225. Allocate memory. If an error ocurrs, jump to input loop */
  226. void    *p;
  227.  
  228.     p = malloc(bytes);
  229.     if (p==NULL) {
  230.         errorf(TRUE,"Malloc");
  231.         abandonimage();
  232.         do_break();
  233.         return NULL;
  234.     }
  235.     return p;
  236. }
  237.  
  238.  
  239. char    valid_keys[4];    /* can be c, q, and/or r */
  240.  
  241. void newpage(char *keys) {
  242. /*   ^^^^^^^
  243. Set up a new paging cycle. <keys> contains a list of characters that may be
  244. pressed. */
  245.     strcpy(valid_keys,keys);
  246.     lineno=1;
  247. }
  248.  
  249.  
  250. char nextline() {
  251. /*   ^^^^^^^^
  252. Anvance the line counter of the internal pager. Stop at a prompt, if the
  253. screen is full. Return the pressed character or '\0' */
  254. char    answer;
  255. int    i;
  256.  
  257.     if (Break_Wish) do_break();
  258.     if ((lineno==0) || (pagelen==0) || (Verb < 1)) return 0;
  259.     lineno++;
  260.     if (lineno+1>pagelen) {
  261.         printm(1,"-- M o r e --   ");
  262.         if (*valid_keys!=0) putcharm(1,'(');
  263.         for (i=0; i<strlen(valid_keys);i++) {
  264.             if (i>0) printm(1,", ");
  265.             switch (valid_keys[i]) {
  266.             case 'c': printm(1,"`c' = continous");    break;
  267.             case 'q': printm(1,"`q' = quit");    break;
  268.             case 'r': printm(1,"`r' = restart");    break;
  269.             default:  errorf(FALSE,"--==>>> nextline");
  270.             }
  271.         }
  272.         if (*valid_keys!=0) putcharm(1,')');
  273.  
  274.         answer = tolower(wait_for_key(0,TRUE));
  275.         putcharm(1,10);
  276.         if (Break_Wish) do_break();
  277.         if (answer=='c' && strchr(valid_keys,'c')!=NULL) {
  278.             lineno=-1;
  279.             return 'c';
  280.         }
  281.         lineno=1;
  282.         if (strchr(valid_keys,answer)!=NULL) return answer;
  283.     }
  284.     return 0;
  285. }
  286.  
  287.  
  288. char *repstr(char c, int times) {
  289. /*    ^^^^^^
  290. Form a string out of <times> <c>.
  291. There must only be one repstr in a printf statement!!!
  292. */
  293. int    i;
  294. static    char str[INPUTLEN];
  295.     for (i=0;i<times;i++) {
  296.         if (i==INPUTLEN) break;
  297.         str[i]=c;
  298.     }
  299.     str[i]=0;
  300.     return str;
  301. }
  302.  
  303.  
  304. char *show_format (uchar sec_offset) {
  305. /*    ^^^^^^^^^^^ */
  306. static char result[20];
  307.     switch (sec_offset ) {
  308.         case SYSTEMFORMAT:    strcpy(result,"System Format"); break;
  309.         case DATAFORMAT:    strcpy(result,"Data Format"); break;
  310.         case IBMFORMAT:     strcpy(result,"IBM Format"); break;
  311.         case VORTEXFORMAT:     strcpy(result,"Vortex Format"); break;
  312.         default:        strcpy(result,"Unknown Format");
  313.     }
  314.     return result;
  315. }
  316.  
  317.  
  318. char *show_mode (int m)  {
  319. /*    ^^^^^^^^^ */
  320. static char result[10];
  321.     switch (m) {
  322.     case M_BIN:  strcpy(result,"Binary"); break;
  323.     case M_TEXT: strcpy(result,"Text"); break;
  324.     case M_AUTO: strcpy(result,"Auto"); break;
  325.     }
  326.     return result;
  327. }
  328.  
  329.  
  330.  
  331. void reparse (int argnb) {
  332. /*   ^^^^^^^
  333. transform the parsed command line back to one string containing all
  334. arguments from "argnb" to last argument.*/
  335. int    i;
  336. char    *p;
  337.     for (i=argnb; i<nbof_args; i++) {
  338.         p = arg[i];
  339.         while (*p) p++;
  340.         *p = ' ';    /* replace terminating 0 with space */
  341.     }
  342. }
  343.  
  344.  
  345.  
  346. void expand_percent(char *from, char *to, int max) {
  347. /*   ^^^^^^^^^^^^^^
  348. WARNING: this function needs sprintf to return int, and not char* ! */
  349. bool    active = *disk_header.tag;
  350. char    buf[256];
  351. char    *t, *t0;
  352.  
  353.     t0 = t = Malloc(max+80);    /* 80 (>len(%V)) as overflow area */
  354.  
  355.     while (*from)  {
  356.         if (*from!='%') *t++=*from;
  357.         else  {
  358.             from++;
  359.             switch (*from) {
  360.             case 'u':
  361.             case 'U': if (active)
  362.                     t+=sprintf(t,"%d",cur_user);
  363.                   else
  364.                     *t++='#';
  365.                   break;
  366.             case 'i': if (active)
  367.                     t+=sprintf(t,"%s",imagename);
  368.                   else
  369.                     *t++='#';
  370.                   break;
  371.             case 'I': if (active)
  372.                     t+=sprintf(t,"%s",full_imagename);
  373.                   else
  374.                     *t++='#';
  375.                   break;
  376.             case 'f': if (active)
  377.                     t+=sprintf(t,"%5.1f",100.00-percentage);
  378.                   else
  379.                     *t++='#';
  380.                   break;
  381.             case 'F': if (active)
  382.                     t+=sprintf(t,"%ld",
  383.                         (long)free_blks*dpb->BLS);
  384.                   else
  385.                     *t++='#';
  386.                   break;
  387.             case 'a': if (active)
  388.                     t+=sprintf(t,"%5.1f",percentage);
  389.                   else
  390.                     *t++='#';
  391.                   break;
  392.             case 'A': if (active)
  393.                     t+=sprintf(t,"%ld",
  394.                         (long)allocated_blks*1024);
  395.                   else
  396.                     *t++='#';
  397.                   break;
  398.             case 'c':
  399.             case 'C': t+=sprintf(t,"%s",getwd(buf));
  400.                   break;
  401.             case 'v': if (PATCHLEVEL==0)
  402.                     t+=sprintf(t,"%d.%d",
  403.                         MAJORVERSION,MINORVERSION);
  404.                   else
  405.                     t+=sprintf(t,"%d.%dpl%d",
  406.                     MAJORVERSION,MINORVERSION,PATCHLEVEL);
  407.                   break;
  408.             case 'V': t+=sprintf(t,"%d.%dpl%d (%s)",
  409.                 MAJORVERSION,MINORVERSION,PATCHLEVEL,stamp);
  410.                   break;
  411.             case '%': *t++='%'; break;
  412.             case '_': *t++=' '; break;
  413.             case '#': *t++='#'; break;
  414.             case 'e':
  415.             case 'E': *t++=27; break;
  416.             case 'q':
  417.             case 'Q': *t++='"'; break;
  418.             case 's':
  419.             case 'S': *t++=';'; break;
  420.             case 'M':
  421. #if DOS
  422.                 t+=sprintf(t,"%u",coreleft()); break;
  423.                     /* "%lu" if model > medium */
  424. #else
  425.                 t+=sprintf(t,"%lu",coreleft()); break;
  426.                     /* coreleft is def'ed in unix.c */
  427. #endif
  428.             default : *t++='%'; *t++=*from; break;
  429.             }
  430.         }
  431.         if (*from) from++;
  432.  
  433. /* check on string overflow */
  434.         if (t>t0+max) break;
  435.     }
  436.     *t = 0;
  437.  
  438.     strncpy(to,t0,max-1);
  439.     to[max-1] = 0;    /* if t0 is _exactly_ of length max-1 */
  440.     free(t0);
  441. }
  442.  
  443.  
  444. void echom (int v, char *p) {
  445. /*   ^^^^^ */
  446.  
  447. char    buf[256]; /* 3 lines should be enough */
  448.     if (Verb >= v) {
  449.         expand_percent(p,buf,256);
  450.         printf("%s",buf);
  451.     }
  452. }
  453.  
  454.  
  455. bool confirmed()  {
  456. /*   ^^^^^^^^^ */
  457. char    answer;
  458.     printm(1,"[y/N] _");
  459.     if (force||(Verb<1)) {
  460.         printm(3," [Forced]\n");
  461.         return TRUE;
  462.     } else {
  463.         answer = wait_for_key(0,TRUE);
  464.         putcharm(1,10);
  465.         if (Break_Wish) return FALSE;
  466.         return (tolower(answer) == 'y');
  467.     }
  468. }
  469.  
  470.  
  471. int parse_cpm_filename (char *name, int *user, char *root, char *ext) {
  472. /*  ^^^^^^^^^^^^^^^^^^
  473. Split the CP/M conformant <name> "UU:RRRRRRRR.EEE" into its ASCIIZ parts.
  474. <user> will be -1, if no UU: found; -2, if UU: is *:
  475. <ext> will be "", if no .EEE found.
  476. <root> = "" is allowed and signals a missing filename (e.g. dir 1:).
  477. Filenames of kind ".xxx" are not possible.
  478. The <root> or <ext> parts can be longer than 8 or 3 due to "[]" wildcards!
  479. Errorcode is 1 on error.
  480. */
  481. char    *p, *q, *r;        /* temp pointer */
  482. int    i;
  483.  
  484.     *user = -1;
  485.     *root = 0;
  486.     *ext = 0;
  487.  
  488. /* scan usernumber */
  489.     p = strchr(name,':');
  490.     if (p!=NULL) {
  491.         if ((name[0]=='*') && (name[1]==':')) {
  492.             *user = -2;
  493.             name += 2;
  494.         } else {
  495.             *user = (int)strtoul(name,&q,0);
  496.             if ((*user<0) || (*user>255) || (*q!=':')
  497.                             || (errno==ERANGE))
  498.                 return 1;
  499.             name = p+1;
  500.         }
  501.     }
  502.  
  503. /* scan root part */
  504.     p = name;
  505.     i = 0;
  506.     r = root;
  507.     while ((*p!='.') && *p && i<8) {
  508.         *r++ = *p++;
  509.         i++;
  510.     }
  511.     *r=0;
  512.     q=strchr(p,'.');
  513.     if (q) p=q;
  514.  
  515. /* scan extension part */
  516.     if (*p) strcpy(ext,p+1);
  517.  
  518.     
  519. /* convert to upper case */
  520.     upper(root);
  521.     upper(ext);
  522.  
  523.     if (*root==0 && *ext!=0) return 1;
  524.     return 0;
  525. }
  526.  
  527.  
  528.  
  529. int parse_filename (char *name, int *drive, char *path, char *root, char *ext) {
  530. /*  ^^^^^^^^^^^^^^
  531. Split the DOS conformant <name> "D:\PP\..\PP\RRRRRRRR.EEE" into its parts.
  532. <drive> will be 0, if no D: was found, and 1 for A:, 2 for B:, and so on;
  533. <path> contains a trailing backslash (i.e. at least "\").
  534. On UNIX systems <root> may contain dots and <ext> is always empty.
  535. Errorcode is 1 on error
  536. */
  537. char    *p;    /* temp pointer */
  538. #if DOS
  539. char    *r, *q;
  540. int    i;
  541. #endif
  542.  
  543.     *drive = 0;
  544.     *path = 0;
  545.     *root = 0;
  546.     *ext = 0;
  547.  
  548. #if DOS
  549. /* scan drive */
  550.     if ((*name!=0) && (name[1]==':')) {
  551.         *drive = tolower(*name)-'a'+1;
  552.         if ((*drive<1) || (*drive>26)) return 1;
  553.         name += 2;
  554.     }
  555. #endif
  556.  
  557. /* scan path */
  558.     p = strrchr(name,DIRSEPARATOR);
  559.     if (p!=NULL) {            /* else no "\" found, path is empty */
  560.         strncpy(path,name,p-name+2);
  561.         name = p+1;
  562.     }
  563.  
  564. /* scan root part */
  565.     if (*name == 0) return 1;
  566.  
  567. #if UNIX
  568.     strcpy(root,name);
  569. #else
  570.     r = root;
  571.     i = 0;
  572.     while ((*name!='.') && *name && i<8) {
  573.         if (*name==':') return 1;    /* possibly mislead drive */
  574.         *r++ = *name++;
  575.     }
  576.     *r=0;
  577.     q=strchr(p,'.');
  578.     if (q) p=q;
  579.  
  580. /* scan extension part */
  581.     if (*name) strncpy(ext,name+1,4);
  582.  
  583. #endif
  584.  
  585.  
  586. #if DOS
  587. /* convert to upper case */
  588.     upper(path);
  589.     upper(root);
  590.     upper(ext);
  591. #endif
  592.  
  593.     return 0;
  594. }
  595.  
  596.  
  597. int internal_pager(char *filename) {
  598. /*  ^^^^^^^^^^^^^^
  599. Display the file with stops after each screen */
  600. FILE    *file;
  601. char    line[256];
  602. char    key;
  603.  
  604.     file = fopen(filename,"r");
  605.     if (file==NULL) return errorf(TRUE,"I can't display \"%s\"",filename);
  606.  
  607.     newpage("cqr");
  608.     while (fgets(line,256,file)) {
  609.         printm(0,"%s",line);
  610.         key = nextline();
  611.         if (key=='r') {
  612.             fseek(file,0L,SEEK_SET);
  613.         }
  614.         if (key=='q') break;    
  615.     }
  616.     fclose(file);
  617.     return 0;
  618. }
  619.  
  620. int pager(char *filename) {
  621. /*  ^^^^^
  622. Display the file <filename> with the lister program from the environment
  623. variable %PAGER or with the internal_pager()
  624. */
  625. char    buf[INPUTLEN];
  626. char    *pag;
  627. int    err;
  628.  
  629.     pag = getenv("PAGER");
  630.     if (pag==NULL)    {
  631.         /* strcpy(buf,PAGERDEFAULT);*/
  632.         internal_pager(filename);
  633.         return 0;
  634.     } else {
  635.         strcpy(buf,pag);
  636.     }
  637.     strcat(buf," ");
  638.     strcat(buf,filename);
  639.  
  640.     err = system(buf);
  641.     if ((err==-1) || (err==127)) return -1;
  642.  
  643.     return 0;
  644. }
  645.  
  646.  
  647. void str2mem(char *mem, char *str, int spc) {
  648. /*   ^^^^^^^
  649. Copy the ASCIIZ string at <str> to position <mem> without trailing 0.
  650. Fill the memory at <mem> with <spc> spaces.
  651. */
  652. int    i;
  653.  
  654.     memset(mem,' ',spc);
  655.     i=0;
  656.     while (str[i]) {
  657.         mem[i] = str[i];
  658.         i++;
  659.     }
  660. }
  661.  
  662.  
  663.  
  664. void build_cpm_name(char *buf, int user, char *root, char *ext) {
  665. /*   ^^^^^^^^^^^^^^
  666. Construct a CP/M name out of the given stuff.
  667. If <user> = -1, no usernumber is prepended,
  668. if <user> = -2, a * (wild user) is prepended.
  669. If <ext> = "", the last char is "."!
  670. <buf> must point to memory of at least 3+1+8+1+3+1=17 Byte (UUU:RRRRRRRR.EEE0).
  671. */
  672.     
  673.     *buf = 0;
  674.     if (user==-2) strcpy(buf,"*:");
  675.     if (user>=0) sprintf(buf,"%d:",user);
  676.  
  677.     strcat(buf,root);
  678.     strcat(buf,".");
  679.     if (*ext) {
  680.         strcat(buf,ext);
  681.     }
  682. }
  683.  
  684.  
  685. void build_cpm_name_32(char *buf, int user, char *root, char *ext) {
  686. /*   ^^^^^^^^^^^^^^^^^
  687. The same function as <build_cpm_name> except, that <root> and <ext> are
  688. considered as padded with ' ' (= ASCII 32) (as in <DirEntry>)
  689. */
  690. int    j;
  691.  
  692.     *buf = 0;
  693.     if (user==-2)    {strcpy(buf,"*:"); buf +=2;}
  694.     if (user>=0)    buf += sprintf(buf,"%d:",user);
  695.  
  696.     memcpy(buf,root,8);
  697.     j=7; while (buf[j] == ' ') {j--;}; j++;
  698.     buf[j]='.'; j++;
  699.     if (strncmp(ext,"   ",3)!=0) {
  700.         memcpy(&buf[j],ext,3); j+=2;
  701.         while (buf[j] == ' ') {j--;}; j++;
  702.     }
  703.     buf[j]=0;
  704. }
  705.  
  706.  
  707. bool has_wildcards(char os_tag, char *name) {
  708. /*   ^^^^^^^^^^^^^
  709. Checks whether <name> contains wildcard characters according to match.h
  710. (if <os_tag> == 'c' ( *?[] )) or to DOS standards (if <os_tag> == 'd'
  711. ( *? )).
  712. */
  713. char    wild[10];
  714.     if (os_tag=='c')    strcpy(wild,"*?[]");    /* !^- ??? */
  715.     else if (os_tag == 'd') strcpy(wild,"*?");
  716.     else return errorf(FALSE,"--==>>> has_wildcards");
  717.  
  718.     while (*name) {
  719.         if (strchr(wild,*name) != NULL) return TRUE;
  720.         name++;
  721.     }
  722.     return FALSE;
  723. }
  724.  
  725.  
  726. char *show_hex(int nr, uchar *buf, int size) {
  727. /*    ^^^^^^^^
  728. Formats a hexdump line out out <size> bytes at <buf>. Prefix the line with
  729. <nr> as address. This function uses a static variable as temporary buffer, so
  730. don't call it twice in a function.
  731. */
  732. static char line[INPUTLEN];
  733. int    i;
  734. char    *p;
  735. uchar    c;
  736.  
  737.     p = line;
  738.     p += sprintf(p,"%6X %c ",nr,vert);
  739.     for (i=0;i<size;i++) {
  740.         p += sprintf(p,"%2X ",buf[i]);
  741.     }
  742.     p += sprintf(p," %c ",vert);
  743.     for (i=0;i<size;i++) {
  744.         if (buf[i]<32)        c=' ';
  745.         else if (buf[i]>=127)    c='~';
  746.         else            c=buf[i];
  747.         p += sprintf(p,"%c",c);
  748.     }
  749. /*    *(p++) = '\n';*/
  750.     return line;
  751. }    
  752.